﻿using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Castle.Facilities.Logging;
using Abp.AspNetCore;
using Abp.Castle.Logging.Log4Net;
using FwProject.Authentication.JwtBearer;
using FwProject.Configuration;
using FwProject.Identity;
using FwProject.Web.Resources;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using Newtonsoft.Json;
using Abp.EntityFrameworkCore;
using FwProject.EntityFrameworkCore;
using System.IO;
using FwProject.Comm;
using Abp.Dependency;
using Abp.PlugIns;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal;
using FwProject.EFCoreAttribut;

#if FEATURE_SIGNALR
using Owin;
using Abp.Owin;
using FwProject.Owin;
#elif FEATURE_SIGNALR_ASPNETCORE
using Abp.AspNetCore.SignalR.Hubs;
#endif

namespace FwProject.Web.Startup
{
    public class Startup
    {
        private readonly IConfigurationRoot _appConfiguration;
        private readonly IHostingEnvironment _hostingEnvironment;
        public Startup(IHostingEnvironment env)
        {
            _appConfiguration = env.GetAppConfiguration();
            _hostingEnvironment = env;
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {

            services.AddAbpDbContext<FwProjectDbContext>(options =>
            {
                FwProjectDbContextConfigurer.Configure(options.DbContextOptions, options.ConnectionString);
            });
#if DEBUG
            services.AddMiniProfiler().AddEntityFramework();
#endif

            // services.AddSingleton<ICoreConventionSetBuilder, FwCoreConventionSetBuilder>();

            // MVC
            services.AddMvc(
                options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute())
            ).AddJsonOptions(o => o.SerializerSettings.DateFormatString = "yyyy-MM-dd").AddJsonOptions(o =>
            {
                o.SerializerSettings.MaxDepth = 2;
                o.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;
                o.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

            });

            services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));
            IdentityRegistrar.Register(services);
            AuthConfigurer.Configure(services, _appConfiguration);

            services.AddScoped<IWebResourceManager, WebResourceManager>();

#if FEATURE_SIGNALR_ASPNETCORE
            services.AddSignalR();
#endif
            // Configure Abp and Dependency Injection
            return services.AddAbp<FwProjectWebMvcModule>(
                // Configure Log4Net logging

                options =>
                {
                    options.IocManager.IocContainer.AddFacility<LoggingFacility>(f => f.UseAbpLog4Net().WithConfig("log4net.config"));
                    options.PlugInSources.AddFolder(Path.Combine(_hostingEnvironment.WebRootPath, "AbpPlugins"), SearchOption.AllDirectories);
                }
            );
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseAbp(); // Initializes ABP framework.

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseAuthentication();

            app.UseJwtTokenMiddleware();

#if FEATURE_SIGNALR
            // Integrate with OWIN
            app.UseAppBuilder(ConfigureOwinServices);
#elif FEATURE_SIGNALR_ASPNETCORE
            app.UseSignalR(routes =>
            {
                routes.MapHub<AbpCommonHub>("/signalr");
            });
#endif
#if DEBUG
                    app.UseMiniProfiler();
#endif

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "defaultWithArea",
                    template: "{area}/{controller=Home}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

#if FEATURE_SIGNALR
        private static void ConfigureOwinServices(IAppBuilder app)
        {
            app.Properties["host.AppName"] = "FwProject";

            app.UseAbp();

            app.MapSignalR();
        }
#endif
    }
}
